#! /bin/bash

PROFILE=prod
MODULES=("admin")
JARS=("sloth-upms-biz.jar")

JDK_PATH="/usr/local/java/jdk-17.0.9"
BASE_PATH="/cn/s1995/sloth/${PROFILE}"
JAR_PATH="${BASE_PATH}/jars"
GC_PATH="${BASE_PATH}/logs/gc"
MEM_MS='512m'
MEM_MX='512m'
MEM_MN='256m'

# 初始化启动配置-动态获取JDK路径和设置java堆内存参数
function initStartConfig() {
    echo ""
	# 如果没有设置JDK，则尝试动态获取JDK路径
    if [ -z "$JDK_PATH" ]; then
		# 尝试获取JDK路径
		JDK_PATH=$(readlink -f /usr/bin/java | sed "s:bin/java::")
		if [ -z "$JDK_PATH" ]; then
			# 如果未找到JDK路径，退出脚本
			echo "无法找到JDK路径，请确保Java已安装或手动设置JDK_PATH变量"
			exit 1
		fi
		echo ""
		echo "JDK路径: $JDK_PATH"
	fi

    # 如果没有设置堆内存值，则根据服务器资源动态设置堆内存大小
    if [ -z "$MEM_MS" ] || [ -z "$MEM_MX" ] || [ -z "$MEM_MN" ]; then
        CPU_CORES=$(nproc)
        TOTAL_MEM=$(free -m | awk '/^Mem:/{print $2}')
        MEM_MX=$(($TOTAL_MEM / 2))
        MEM_MS=$(($MEM_MX / 2))
        # 新生代内存设置为堆内存的1/8
        # MEM_MN=$(($TOTAL_MEM / 8))"m"
        # 如果CPU核心数大于等于4，则设置新生代内存为堆内存的一半，否则设置为堆内存的四分之一
        if [ $CPU_CORES -ge 4 ]; then
            MEM_MN=$(($MEM_MS / 2))
        else
            MEM_MN=$(($MEM_MS / 4))
        fi
        echo "CPU核心数: $CPU_CORES, 总内存: $TOTAL_MEM"
    fi

    echo "堆内存参数: -Xms$MEM_MS -Xmx$MEM_MX -Xmn$MEM_MN"
}

# 输出模块信息
function outModels() {
    echo ".................................服务模块.............................................."
    for MODULE in "${MODULES[@]}"; do
        echo "$MODULE"
    done
    echo ""
    echo "示例用法："
    echo "启动所有服务：sh boot.sh start all"
    echo "停止特定服务：sh boot.sh stop admin"
    echo "查询特定服务状态：sh boot.sh status app"
    echo "重启所有服务：sh boot.sh restart all"
    echo "......................................................................................"
    echo ""
}

# 开始服务
function startService() {
    echo ""
    local MODULE_NAME=$1
    local JAR_NAME=$2
#    echo "模块名: $MODULE_NAME, jar名: $JAR_NAME"
    # 初始化启动配置
    initStartConfig

    if [ ! -d "$GC_PATH" ]; then
        mkdir -p "$GC_PATH"
    fi

    PID=$(getServicePID "$JAR_NAME")
    if [ -n "$PID" ]; then
        echo "服务 -> 【$MODULE_NAME】 已经运行, PID=$PID"
    else
        echo "启动 $MODULE_NAME..."
        echo "启动命令 -> "$JDK_PATH"/bin/java -server -Dfile.encoding=utf-8 -Xms$MEM_MS -Xmx$MEM_MX -Xmn$MEM_MN -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="$GC_PATH"/oom_$(date +"%Y-%m-%d").hprof -jar "$JAR_PATH"/"$JAR_NAME" --spring.profiles.active=$PROFILE"
        sudo nohup "$JDK_PATH"/bin/java -server -Dfile.encoding=utf-8 -Xms$MEM_MS -Xmx$MEM_MX -Xmn$MEM_MN -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="$GC_PATH"/oom_$(date +"%Y-%m-%d").hprof -jar "$JAR_PATH"/"$JAR_NAME" --spring.profiles.active=$PROFILE > /dev/null 2>&1 &
        echo "服务 -> 【$MODULE_NAME】 启动成功"
    fi
}

# 停止服务
function stopService() {
    echo ""
    local MODULE_NAME=$1
    local JAR_NAME=$2
#    echo "模块名: $MODULE_NAME, jar名: $JAR_NAME"
    PIDS=$(getServicePID "$JAR_NAME")
    if [ -n "$PIDS" ]; then
        for PID in $PIDS; do
            echo "尝试停止 $MODULE_NAME (PID=$PID)..."
            # kill进程
            sudo kill -9 "$PID"

            # 等待最多30秒，检查进程是否已经退出
            for i in {1..30}; do
                if ! ps -p "$PID" > /dev/null; then
                    echo "$MODULE_NAME 已停止."
                    break
                fi
                sleep 1
            done

            if ps -p "$PID" > /dev/null; then
                echo "$MODULE_NAME 未在指定时间内停止，尝试强制停止..."
                # 如果进程仍然存在，使用kill -9强制终止
                sudo kill -9 "$PID"
                echo "$MODULE_NAME 已强制停止."
            fi
        done
    else
        echo "服务 -> 【$MODULE_NAME】 未运行."
    fi
}

# 服务状态
function statusService() {
    echo ""
    local MODULE_NAME=$1
    local JAR_NAME=$2
#    echo "模块名: $MODULE_NAME, jar名: $JAR_NAME"
    PID=$(getServicePID "$JAR_NAME")
    if [ -z "$PID" ]; then
        echo "服务 -> 【$MODULE_NAME】 未运行"
    else
        echo "服务 -> 【$MODULE_NAME】 运行中, PID=$PID"
    fi
}

# 获取服务PID
function getServicePID() {
    echo ""
    local JAR_NAME=$1
    echo $(ps -ef | grep java | grep "$JAR_PATH/$JAR_NAME" | grep -v grep | awk '{print $2}')
}

# 控制服务
function controlService() {
    local command=$1
    local target=$2
    case "$command" in
        "start" | "stop" | "status")
            for i in "${!MODULES[@]}"; do
                # 如果target为all或者与当前模块名相同，则执行对应操作
                if [ "$target" == "all" ] || [ "$target" == "${MODULES[$i]}" ]; then
                    "${command}Service" "${MODULES[$i]}" "${JARS[$i]}"
                fi
            done
            ;;
        "restart")
            for i in "${!MODULES[@]}"; do
                if [ "$target" == "all" ] || [ "$target" == "${MODULES[$i]}" ]; then
                    local moduleName="${MODULES[$i]}"
                    local jarName="${JARS[$i]}"
                    stopService "$moduleName" "$jarName"
                    sleep 3  # 等待几秒钟，以确保服务已完全停止
                    startService "$moduleName" "$jarName"
                fi
            done
            ;;
        *)
            echo "不支持的操作: $command"
            exit 1
            ;;
    esac
}

# 主逻辑
outModels

case "$1" in
    start|stop|restart|status)
        controlService "$1" "${2:-all}"
        ;;
    *)
        echo "用法: $0 {start|stop|restart|status} {all|moduleName}"
        exit 1
        ;;
esac
